/*
 * Copyright 2024 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.pajamas.starter.integration.spring.doc;

import com.google.common.collect.Maps;

import org.apache.commons.collections4.MapUtils;
import org.pajmas.daydream.building.AbstractEzBuilder;

import java.util.Map;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;

/**
 * @author william
 * @since 2024/1/16
 */

public final class OpenApiBuilder extends AbstractEzBuilder<OpenAPI> {
    private final Map<String, Object> authorExtensions;
    private final Map<String, Object> licenseExtensions;
    private final Map<String, Object> infoExtensions;
    private String authorName;
    private String authorEmail;
    private String authorLink;
    private String licenseName;
    private String licenseLink;
    private String licenseIdentifier;
    private String docTitle;
    private String docDescription;
    private String version;
    private String serviceLink;

    private OpenApiBuilder() {
        this.authorExtensions = Maps.newLinkedHashMap();
        this.licenseExtensions = Maps.newLinkedHashMap();
        this.infoExtensions = Maps.newLinkedHashMap();
    }

    public static OpenApiBuilder newBuilder() {
        return new OpenApiBuilder();
    }

    public OpenApiBuilder authorName(String authorName) {
        this.authorName = authorName;
        return this;
    }

    public OpenApiBuilder authorEmail(String authorEmail) {
        this.authorEmail = authorEmail;
        return this;
    }

    public OpenApiBuilder authorLink(String authorLink) {
        this.authorLink = authorLink;
        return this;
    }

    public OpenApiBuilder licenseName(String licenseName) {
        this.licenseName = licenseName;
        return this;
    }

    public OpenApiBuilder licenseLink(String licenseLink) {
        this.licenseLink = licenseLink;
        return this;
    }

    public OpenApiBuilder licenseIdentifier(String licenseIdentifier) {
        this.licenseIdentifier = licenseIdentifier;
        return this;
    }

    public OpenApiBuilder docTitle(String docTitle) {
        this.docTitle = docTitle;
        return this;
    }

    public OpenApiBuilder docDescription(String docDescription) {
        this.docDescription = docDescription;
        return this;
    }

    public OpenApiBuilder version(String version) {
        this.version = version;
        return this;
    }

    public OpenApiBuilder serviceLink(String serviceLink) {
        this.serviceLink = serviceLink;
        return this;
    }

    public OpenApiBuilder putAuthorExtension(String key, Object value) {
        this.authorExtensions.put(key, value);
        return this;
    }

    public OpenApiBuilder putAllAuthorExtensions(Map<String, Object> authorExtensions) {
        if (MapUtils.isEmpty(authorExtensions)) {
            return this;
        }
        this.authorExtensions.putAll(authorExtensions);
        return this;
    }

    public OpenApiBuilder putLicenseExtension(String key, Object value) {
        this.licenseExtensions.put(key, value);
        return this;
    }

    public OpenApiBuilder putAllLicenseExtensions(Map<String, Object> licenseExtensions) {
        if (MapUtils.isEmpty(licenseExtensions)) {
            return this;
        }
        this.licenseExtensions.putAll(licenseExtensions);
        return this;
    }

    public OpenApiBuilder putInfoExtension(String key, Object value) {
        this.infoExtensions.put(key, value);
        return this;
    }

    public OpenApiBuilder putAllInfoExtensions(Map<String, Object> infoExtensions) {
        if (MapUtils.isEmpty(infoExtensions)) {
            return this;
        }
        this.infoExtensions.putAll(infoExtensions);
        return this;
    }

    @Override
    public OpenAPI internalBuild() {
        Contact author = new Contact()
                .name(this.authorName)
                .email(this.authorEmail)
                .url(this.authorLink)
                .extensions(this.authorExtensions);

        License license = new License()
                .name(this.licenseName)
                .url(this.licenseLink)
                .identifier(this.licenseIdentifier)
                .extensions(this.licenseExtensions);

        Info info = new Info()
                .title(this.docTitle)
                .description(this.docDescription)
                .version(this.version)
                .termsOfService(this.serviceLink)
                .extensions(this.infoExtensions)
                .contact(author)
                .license(license);

        return new OpenAPI()
                .info(info);
    }

    public interface Customizer extends AbstractEzBuilder.Customizer<OpenAPI, OpenApiBuilder> {
    }
}
